
/*
 *  Copyright 2004-2005 Saybot LLC.  All Rights Reserved.
 *  Unpublished -- rights reserved under the copyright laws of the
 *  United States.  USE OF A COPYRIGHT NOTICE IS PRECAUTIONARY ONLY
 *  AND DOES NOT IMPLY PUBLICATION OR DISCLOSURE.
 *
 *  THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE SECRETS
 *  OF SAYBOT LLC.  USE, DISCLOSURE, OR REPRODUCTION IS
 *  PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF
 *  SAYBOT LLC.
 *
 *     ***  RESTRICTED RIGHTS LEGEND  ***
 *
 *  Use, duplication, or disclosure by the Government is subject to
 *  restrictions as set forth in subparagraph (c)(1)(ii) of the
 *  Rights in Technical Data and Computer Software clause at DFARS
 *  252.227-7013 or subparagraphs (c)(1) and (2) of Commercial
 *  Computer Software -- Restricted Rights at 48 CFR 52.227-19, as
 *  applicable.
 */

package com.cy.dao;



import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;


/**
 
 */
public class BaseDAOHibernate<T> extends HibernateDaoSupport implements BaseDAO<T> {
	protected final Logger	log	= Logger.getLogger(getClass());
	
	/**
	 * 采用@Autowired按类型注入SessionFactory, 当有多个SesionFactory的时候Override本函数.
	 */
	@Resource(name="sessionFactory")
	public void setLocalSessionFactory(final SessionFactory sessionFactory) {
		super.setSessionFactory(sessionFactory);
	}

	/**
	 * @see org.appfuse.dao.DAO#doSaveObject(java.lang.Object)
	 */
	public void saveObject(T o) {
		getHibernateTemplate().saveOrUpdate(o);
	}

	/**
	 * @see org.appfuse.dao.DAO#getObject(java.lang.Class, java.io.Serializable)
	 */
	public T getObject(Class<T> clazz, Serializable id) {
		Object o = getHibernateTemplate().get(clazz, id);

		if (o == null) { throw new ObjectRetrievalFailureException(clazz, id); }

		return (T) o;
	}

	/**
	 * @see org.appfuse.dao.DAO#getObjects(java.lang.Class)
	 */	
	public List<T> getObjects(Class<T> clazz) {
		return (List<T>) getHibernateTemplate().loadAll(clazz);
	}

	/**
	 * @see org.appfuse.dao.DAO#removeObject(java.lang.Class,
	 *      java.io.Serializable)
	 */
	public void removeObject(Class<T> clazz, Serializable id) {
		getHibernateTemplate().delete(getObject(clazz, id));
	}

	public List<T> getObjectsByPageSize(final String queryString, final String[] params, final Object[] values, final Integer startIndex, final Integer pageSize) {
		return (List<T>) getHibernateTemplate()
				.execute(new HibernateCallback(){
					public List<T> doInHibernate(Session session) {
						Query queryObject = session.createQuery(queryString);
						for (int i = 0; i < params.length; i++) {
							if (values[i] instanceof Collection) {
								queryObject.setParameterList(params[i], (Collection) values[i]);
							} else if (values[i] instanceof Object[]) {
								queryObject
										.setParameterList(params[i], (Object[]) values[i]);
							} else {
								queryObject.setParameter(params[i], values[i]);
							}
						}
						if (startIndex != null) {
							queryObject.setFirstResult(startIndex.intValue());
						}
						if (pageSize != null) {
							queryObject.setMaxResults(pageSize.intValue());
						}
						List<T> cats = queryObject.list();
						return cats;
					}
				});
	}

	private void batchSaveObject(final Collection<T> ts) {
		this.getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) {
				int i = 0;
				Iterator<T> iterable = ts.iterator();
				while (iterable.hasNext()) {
					session.saveOrUpdate(iterable.next());
					if (i % 30 == 0) {
						session.flush();
						session.clear();
					}
					i++;
				}
				return ts;
			}
		});
	}

	private void batchSaveObject(final T[] ts) {
		this.getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) {
				for (int i = 0; i < ts.length; i++) {
					session.saveOrUpdate(ts[i]);
					if (i % 30 == 0) {
						session.flush();
						session.clear();
					}
				}
				return ts;
			}
		});
	}

	private void batchRemoveObject(final Class<T> clazz, final Collection<Serializable> ids) {
		this.getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) {
				int i = 0;
				Iterator<Serializable> iterable = ids.iterator();
				while (iterable.hasNext()) {
					session.delete(session.get(clazz, iterable.next()));
					if (i % 30 == 0) {
						session.flush();
						session.clear();
					}
					i++;
				}
				return ids;
			}
		});
	}

	private void batchRemoveObject(final Class<T> clazz, final Serializable[] ids) {
		this.getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) {
				for (int i = 0; i < ids.length; i++) {
					session.delete(session.get(clazz, ids[i]));
					if (i % 30 == 0) {
						session.flush();
						session.clear();
					}
				}
				return ids;
			}
		});
	}

	public List<T> getObjectsByParam(String queryString, String[] params, Object[] values) {
		return getObjectsByPageSize(queryString, params, values, null, null);
	}

	public int getCount(String queryString, String[] params, Object[] values) {
		List list = getObjectsByParam(queryString, params, values);
		if (list == null || list.size() == 0) { return 0; }
		Integer count = Integer.parseInt(list.get(0).toString());
		return count == null ? 0 : count.intValue();
	}

	public int getCountBySQLQuery(final String queryString, final String[] params, final Object[] values) {
		return (Integer) getHibernateTemplate()
				.execute(new HibernateCallback(){
					public Integer doInHibernate(Session session) {
						Query queryObject = session.createSQLQuery(queryString);
						for (int i = 0; i < params.length; i++) {
							if (values[i] instanceof Collection) {
								queryObject
										.setParameterList(params[i], (Collection) values[i]);
							} else if (values[i] instanceof Object[]) {
								queryObject
										.setParameterList(params[i], (Object[]) values[i]);
							} else {
								queryObject.setParameter(params[i], values[i]);
							}
						}

						List<Object> list = queryObject.list();
						if (list == null || list.size() == 0) { return 0; }
						BigDecimal count = (BigDecimal) list.get(0);
						return count == null ? 0 : Integer.parseInt(count.toString());
					}
				});
	}

	public void saveObjects(T[] ts) {
		batchSaveObject(ts);
	}

	public void saveObjects(Collection<T> ts) {
		batchSaveObject(ts);
	}

	public void removeObjects(Class<T> clazz, Serializable[] ids) {
		batchRemoveObject(clazz, ids);
	}

	public void removeObjects(Class<T> clazz, Collection<Serializable> ids) {
		batchRemoveObject(clazz, ids);
	}

	public T getObject(Class<T> clazz, Serializable id, boolean isLazyDetail) {
		return (T) this.getSession().get(clazz, id);
	}

	public Session getCurrentSession() {
		return this.getSession();
	}
}
